home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / shadow-3.1.4 / groupadd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  7.2 KB  |  392 lines

  1. /*
  2.  * Copyright 1991, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #ifndef lint
  13. static    char    sccsid[] = "@(#)groupadd.c    3.3    08:43:44    9/12/91";
  14. #endif
  15.  
  16. #include <sys/types.h>
  17. #include <stdio.h>
  18. #include <grp.h>
  19. #include <ctype.h>
  20. #include <fcntl.h>
  21.  
  22. #ifdef    BSD
  23. #include <strings.h>
  24. #else
  25. #include <string.h>
  26. #endif
  27.  
  28. #include "config.h"
  29. #include "shadow.h"
  30.  
  31. #ifdef    USE_SYSLOG
  32. #include <syslog.h>
  33. #endif
  34.  
  35. char    group_name[BUFSIZ];
  36. int    group_id;
  37.  
  38. char    *Prog;
  39.  
  40. int    oflg;    /* permit non-unique group ID to be specified with -g         */
  41. int    gflg;    /* ID value for the new group                                 */
  42.  
  43. #ifdef    NDBM
  44. extern    int    gr_dbm_mode;
  45. extern    int    sg_dbm_mode;
  46. #endif
  47. extern    char    *malloc();
  48.  
  49. extern    struct    group    *getgrnam();
  50. extern    struct    group    *gr_next();
  51. extern    int    gr_lock();
  52. extern    int    gr_unlock();
  53. extern    int    gr_rewind();
  54. extern    int    gr_open();
  55.  
  56. #ifdef    SHADOWGRP
  57. extern    int    sgr_lock();
  58. extern    int    sgr_unlock();
  59. extern    int    sgr_open();
  60. #endif
  61.  
  62. /*
  63.  * usage - display usage message and exit
  64.  */
  65.  
  66. usage ()
  67. {
  68.     fprintf (stderr, "usage: groupadd [-g gid [-o]] group\n");
  69.     exit (2);
  70. }
  71.  
  72. /*
  73.  * new_grent - initialize the values in a group file entry
  74.  *
  75.  *    new_grent() takes all of the values that have been entered and
  76.  *    fills in a (struct group) with them.
  77.  */
  78.  
  79. void
  80. new_grent (grent)
  81. struct    group    *grent;
  82. {
  83.     static    char    *empty_list = 0;
  84.  
  85.     memset (grent, 0, sizeof *grent);
  86.     grent->gr_name = group_name;
  87.     grent->gr_passwd = "*";
  88.     grent->gr_gid = group_id;
  89.     grent->gr_mem = &empty_list;
  90. }
  91.  
  92. #ifdef    SHADOWGRP
  93. /*
  94.  * new_sgent - initialize the values in a shadow group file entry
  95.  *
  96.  *    new_sgent() takes all of the values that have been entered and
  97.  *    fills in a (struct sgrp) with them.
  98.  */
  99.  
  100. void
  101. new_sgent (sgent)
  102. struct    sgrp    *sgent;
  103. {
  104.     static    char    *empty_list = 0;
  105.  
  106.     memset (sgent, 0, sizeof *sgent);
  107.     sgent->sg_name = group_name;
  108.     sgent->sg_passwd = "!";
  109.     sgent->sg_adm = &empty_list;
  110.     sgent->sg_mem = &empty_list;
  111. }
  112. #endif    /* SHADOWGRP */
  113.  
  114. /*
  115.  * grp_update - add new group file entries
  116.  *
  117.  *    grp_update() writes the new records to the group files.
  118.  */
  119.  
  120. void
  121. grp_update ()
  122. {
  123.     struct    group    grp;
  124. #ifdef    SHADOWGRP
  125.     struct    sgrp    sgrp;
  126. #endif    /* SHADOWGRP */
  127.  
  128.     /*
  129.      * Create the initial entries for this new group.
  130.      */
  131.  
  132.     new_grent (&grp);
  133. #ifdef    SHADOWGRP
  134.     new_sgent (&sgrp);
  135. #endif    /* SHADOWGRP */
  136.  
  137.     /*
  138.      * Write out the new group file entry.
  139.      */
  140.  
  141.     if (! gr_update (&grp)) {
  142.         fprintf (stderr, "%s: error adding new group entry\n", Prog);
  143.         exit (1);
  144.     }
  145. #ifdef    NDBM
  146.  
  147.     /*
  148.      * Update the DBM group file with the new entry as well.
  149.      */
  150.  
  151.     if (! gr_dbm_update (&grp)) {
  152.         fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog);
  153.         exit (1);
  154.     }
  155.     endgrent ();
  156. #endif    /* NDBM */
  157.  
  158. #ifdef    SHADOWGRP
  159.  
  160.     /*
  161.      * Write out the new shadow group entries as well.
  162.      */
  163.  
  164.     if (! sgr_update (&sgrp)) {
  165.         fprintf (stderr, "%s: error adding new group entry\n", Prog);
  166.         exit (1);
  167.     }
  168. #ifdef    NDBM
  169.  
  170.     /*
  171.      * Update the DBM group file with the new entry as well.
  172.      */
  173.  
  174.     if (! sgr_dbm_update (&sgrp)) {
  175.         fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog);
  176.         exit (1);
  177.     }
  178.     endsgent ();
  179. #endif    /* NDBM */
  180. #endif    /* SHADOWGRP */
  181. #ifdef    USE_SYSLOG
  182.     syslog (LOG_INFO, "new group: name=%s, gid=%d\n",
  183.         group_name, group_id);
  184. #endif    /* USE_SYSLOG */
  185. }
  186.  
  187. /*
  188.  * find_new_gid - find the next available GID
  189.  *
  190.  *    find_new_gid() locates the next highest unused GID in the group
  191.  *    file, or checks the given group ID against the existing ones for
  192.  *    uniqueness.
  193.  */
  194.  
  195. void
  196. find_new_gid ()
  197. {
  198.     struct    group    *grp;
  199.  
  200.     /*
  201.      * Start with some GID value if the user didn't provide us with
  202.      * one already.
  203.      */
  204.  
  205.     if (! gflg)
  206.         group_id = 100;
  207.  
  208.     /*
  209.      * Search the entire group file, either looking for this
  210.      * GID (if the user specified one with -g) or looking for the
  211.      * largest unused value.
  212.      */
  213.  
  214.     for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) {
  215.         if (strcmp (group_name, grp->gr_name) == 0) {
  216.             fprintf (stderr, "%s: name %s is not unique\n",
  217.                 Prog, group_name);
  218.             exit (1);
  219.         }
  220.         if (gflg && group_id == grp->gr_gid) {
  221.             fprintf (stderr, "%s: gid %d is not unique\n",
  222.                 Prog, group_id);
  223.             exit (1);
  224.         }
  225.         if (! gflg && grp->gr_gid >= group_id)
  226.             group_id = grp->gr_gid + 1;
  227.     }
  228. }
  229.  
  230. /*
  231.  * process_flags - perform command line argument setting
  232.  *
  233.  *    process_flags() interprets the command line arguments and sets
  234.  *    the values that the user will be created with accordingly.  The
  235.  *    values are checked for sanity.
  236.  */
  237.  
  238. void
  239. process_flags (argc, argv)
  240. int    argc;
  241. char    **argv;
  242. {
  243.     extern    int    optind;
  244.     extern    char    *optarg;
  245.     char    *end;
  246.     int    arg;
  247.  
  248.     while ((arg = getopt (argc, argv, "og:")) != EOF) {
  249.         switch (arg) {
  250.             case 'g':
  251.                 gflg++;
  252.                 if (! isdigit (optarg[0]))
  253.                     usage ();
  254.  
  255.                 group_id = strtol (optarg, &end, 10);
  256.                 if (*end != '\0') {
  257.                     fprintf (stderr, "%s: invalid group %s\n",
  258.                         Prog, optarg);
  259.                     exit (3);
  260.                 }
  261.                 break;
  262.             case 'o':
  263.                 if (! gflg)
  264.                     usage ();
  265.  
  266.                 oflg++;
  267.                 break;
  268.             default:
  269.                 usage ();
  270.         }
  271.     }
  272.     if (! gflg)
  273.         find_new_gid ();
  274.  
  275.     if (optind == argc - 1)
  276.         strcpy (group_name, argv[argc - 1]);
  277.     else
  278.         usage ();
  279. }
  280.  
  281. /*
  282.  * close_files - close all of the files that were opened
  283.  *
  284.  *    close_files() closes all of the files that were opened for this
  285.  *    new group.  This causes any modified entries to be written out.
  286.  */
  287.  
  288. close_files ()
  289. {
  290.     if (! gr_close ()) {
  291.         fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
  292.         exit (1);
  293.     }
  294.     (void) gr_unlock ();
  295. #ifdef    SHADOWGRP
  296.     if (! sgr_close ()) {
  297.         fprintf (stderr, "%s: cannot rewrite shadow group file\n",
  298.             Prog);
  299.         exit (1);
  300.     }
  301.     (void) sgr_unlock ();
  302. #endif    /* SHADOWGRP */
  303. }
  304.  
  305. /*
  306.  * open_files - lock and open the group files
  307.  *
  308.  *    open_files() opens the two group files.
  309.  */
  310.  
  311. open_files ()
  312. {
  313.     if (! gr_lock ()) {
  314.         fprintf (stderr, "%s: unable to lock group file\n", Prog);
  315.         exit (1);
  316.     }
  317.     if (! gr_open (O_RDWR)) {
  318.         fprintf (stderr, "%s: unable to open group file\n", Prog);
  319.         exit (1);
  320.     }
  321. #ifdef    SHADOWGRP
  322.     if (! sgr_lock ()) {
  323.         fprintf (stderr, "%s: unable to lock shadow group file\n",
  324.             Prog);
  325.         exit (1);
  326.     }
  327.     if (! sgr_open (O_RDWR)) {
  328.         fprintf (stderr, "%s: unable to open shadow group file\n",
  329.             Prog);
  330.         exit (1);
  331.     }
  332. #endif    /* SHADOWGRP */
  333. }
  334.  
  335. /*
  336.  * main - useradd command
  337.  */
  338.  
  339. main (argc, argv)
  340. int    argc;
  341. char    **argv;
  342. {
  343.  
  344.     /*
  345.      * Get my name so that I can use it to report errors.
  346.      */
  347.  
  348.     if (Prog = strrchr (argv[0], '/'))
  349.         Prog++;
  350.     else
  351.         Prog = argv[0];
  352.  
  353. #ifdef    USE_SYSLOG
  354.     openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  355. #endif    /* USE_SYSLOG */
  356.  
  357.     /*
  358.      * The open routines for the DBM files don't use read-write
  359.      * as the mode, so we have to clue them in.
  360.      */
  361.  
  362. #ifdef    NDBM
  363.     gr_dbm_mode = O_RDWR;
  364. #ifdef    SHADOWGRP
  365.     sg_dbm_mode = O_RDWR;
  366. #endif    /* SHADOWGRP */
  367. #endif    /* NDBM */
  368.     process_flags (argc, argv);
  369.  
  370.     /*
  371.      * Start with a quick check to see if the group exists.
  372.      */
  373.  
  374.     if (getgrnam (group_name)) {
  375.         fprintf (stderr, "%s: group %s exists\n", Prog, group_name);
  376.         exit (9);
  377.     }
  378.  
  379.     /*
  380.      * Do the hard stuff - open the files, create the group entries,
  381.      * then close and update the files.
  382.      */
  383.  
  384.     open_files ();
  385.  
  386.     grp_update ();
  387.  
  388.     close_files ();
  389.     exit (0);
  390.     /*NOTREACHED*/
  391. }
  392.